import { useMessage } from '@/hooks/useMessage';
import { useI18n } from '@/locale/index';
import { request as uniClient } from '@/utils/request/uni';
import { isString } from '@/utils/is';
import { isH5 } from '@/utils/platform';
import { ErrorMessageMode } from '#/request';

/**
 * useDownload 是一个定制化的请求钩子，用于处理下载文件。
 * @param requestType 请求的类型：默认：uni。
 * @param url 请求的地址。
 * @param save 是否保存文件
 * @param errorMessageMode 错误消息提示模式
 * @returns 返回一个对象{loading, progress, error, data, run}，包含请求的加载状态、错误信息、响应数据和手动触发请求的函数。
 */
export default function useDownload<
  T = { statusCode: number; tempFilePath: string; fileName: string; fileSize: number },
>(url?: string, save: boolean = false, errorMessageMode: ErrorMessageMode = 'message') {
  const loading = ref(false);
  const progress = ref<OnProgressEvent>({ progress: 0, loaded: 0, total: 0 });
  const error = ref(false);
  const data = ref<T>();

  const { t } = useI18n();
  const { toast, modal } = useMessage();

  /** 运行 */
  const run = async (
    _url: string = url,
    _fileName: string = '',
    _save: boolean = save,
    _errorMessageMode: ErrorMessageMode = errorMessageMode,
  ) => {
    loading.value = true;

    try {
      const result = await uniClient.downloadFile(
        {
          url: _url,
          responseType: 'blob', // 重要：设置响应类型为流，以便于处理进度事件。
          onProgress: (event) => {
            progress.value = {
              progress: event.progress,
              loaded: event.loaded,
              total: event.total,
            };
          },
        },
        {
          errorMessageMode: _errorMessageMode,
        },
      );
      const xhr = uniClient.getTask<any>()?._xhr || {};
      _fileName = _fileName || xhr.response?.name;
      const _fileSize = xhr.response?.size;
      data.value = { ...result, fileName: _fileName, fileSize: _fileSize } as T;
      // 保存文件
      if (_save || isH5) {
        const filePath = result.tempFilePath;
        // #ifdef H5
        const link = document.createElement('a');
        link.href = filePath;
        link.download = _fileName; // a标签添加属性 可以设置下载文件名，如果是空字符串，则使用服务器端设置的文件名。
        link.style.display = 'none';
        // document.body.appendChild(link);
        link.click();
        // URL.revokeObjectURL(filePath);
        // document.body.removeChild(link);
        // or saveAs(filePath,finName); // 需要安装 file-saver --dev @types/file-saver 插件
        // #endif
        //  #ifdef MP-WEIXIN || APP-PLUS
        uni.saveFile({
          tempFilePath: filePath,
          success: function (res) {
            data.value = { ...data.value, ...res } as T;
          },
          fail: function (err) {
            console.error('保存文件错误', err);
            const errMsg = isString(err) ? err : JSON.stringify(err);
            if (_errorMessageMode === 'modal') {
              modal.alert({ title: t('sys.api.errorTip'), content: errMsg });
            } else if (_errorMessageMode === 'message') {
              toast.error({
                content: errMsg,
              });
            }
          },
        });
        // #endif
      }
    } catch {
      error.value = true;
    } finally {
      loading.value = false;
    }
  };

  /** 中断下载 */
  const abort = async () => {
    loading.value = false;

    uniClient.abort();
  };

  return { loading, progress, error, data, run, abort };
}
